/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package argtrust.tidal;

import java.util.Map;
import java.util.LinkedHashMap;
import java.util.Set;

import aima.core.logic.fol.parsing.ast.Sentence;
import argtrust.belief.Belief;
import argtrust.belief.BeliefBase;
import argtrust.belief.ITrustBeliefSemantics;
import argtrust.belief.IndirectBelief;
import argtrust.logic.InferenceRule;
import argtrust.trustnet.Agent;
import argtrust.trustnet.ITrustSemantics;
import argtrust.util.Pair;
import argtrust.measure.Measure;
import argtrust.measure.LevelMeasure;
import argtrust.measure.LevelMeasureOperators;
import argtrust.measure.IMeasureOperators;

/**
 * Beliefs over facts and inference rules are computed from the indirect beliefs
 * of the agent's over the agents who are holding the facts and inference rules.
 * In the case in which multiple agents hold the same fact and inference rule,
 * a tidal-trust style average is applied to average the trust over the facts and
 * inference rules weighted by the holding agents' belief levels over the facts and
 * rules.
 * @author Yuqing Tang
 */
public class TidalTrustBelief implements ITrustBeliefSemantics {

    BeliefBase mBeliefBase;
    TidalTrust mTrustSemantics;
    IMeasureOperators mComparator;

    public IMeasureOperators getOperators() {
        return mComparator;
    }

    public TidalTrustBelief(
            BeliefBase belief_base,
            ITrustSemantics trust_semantics) {
        mBeliefBase = belief_base;
        mTrustSemantics = (TidalTrust) trust_semantics;
        mComparator = trust_semantics.getOperators();
    }
    Map<Pair<Agent, Object>, Measure> mTrustBeliefTable = new LinkedHashMap<Pair<Agent, Object>, Measure>();

    public double getLevel(Measure measure) {
        if (measure.getOpMeasure() instanceof LevelMeasure) {
            return ((LevelMeasure) measure.getOpMeasure()).getLevel();
        } else {
            System.err.println(this.getClass().getName()
                    + " doesn't understand the belief measure");
            if (measure != null) {
                System.err.println("Measure: " + measure.getClass().getName());
            }
            return -1;
        }
    }

    public Measure believe(Agent agent, Object obj) {
        Pair<Agent, Object> key = new Pair<Agent, Object>(agent, obj);
        Measure res = mTrustBeliefTable.get(key);
        if (res == null) {
            Set<Belief> belief_set = mBeliefBase.getBeliefSet(obj);

            double denominator = 0;
            double numerator = 0;
            if (belief_set != null) {
                for (Belief belief : belief_set) {
                    if (agent.equals(belief.getOwner())) {
                        res = new LevelMeasure((LevelMeasure) belief.getMeasure());
                        mTrustBeliefTable.put(key, res);
                        return res;
                    }
                    double tr_level = mTrustSemantics.trustLevel(agent, belief.getOwner());
                    double bl_level = getLevel(belief.getMeasure());
                    numerator += tr_level * bl_level;
                    denominator += bl_level;
                }
            }
            res = new IndirectBelief();
            if (denominator == 0) {
                ((IndirectBelief) res).setMeasure(new LevelMeasure(0));
            } else {

                ((IndirectBelief) res).setMeasure(new LevelMeasure(numerator / denominator));
            }
            mTrustBeliefTable.put(key, res);
        }

        return res;
    }
}
